#!/bin/bash -e
#   * compile instructions: put this file in
#   *         `steamapps/common/Dyson Sphere Program/CustomMod`
#   * folder, open a terminal in the same folder, and execute:
#   *
#   * ```
#   *     chmod +x oni.cs
#   *     ./oni.cs
#   * ```
#   *
#   * then the mod will be compiled automatically.
#   *
#   * Here we wrote a shebang like file, which is correct
#   * in my computer (Manjaro XFCE), if such script do not work
#   * in your computer, you could just try the instructions below :

if [ -z "$__DOTNET_CSC" ]; then
    export __DOTNET_CSC="`find /usr/share/dotnet -type f -name dotnet` `find /usr/share/dotnet -name csc.dll`"
    echo '$'"__DOTNET_CSC not set yet, you should execute"
    echo "export __DOTNET_CSC='$__DOTNET_CSC'"
    echo "manually, or this alert will occur each time you execute this script."
fi

__MODE_VERBOSE=61 # may be modified, check it carefully.
__MODE_DEBUG__=62
__MODE_RELEASE=63

case $1 in
    V)       _MODE__SELECT_=$__MODE_VERBOSE     ;;
    v)       _MODE__SELECT_=$__MODE_VERBOSE     ;;
    VERBOSE) _MODE__SELECT_=$__MODE_VERBOSE     ;;
    verbose) _MODE__SELECT_=$__MODE_VERBOSE     ;;
    D)       _MODE__SELECT_=$__MODE_DEBUG__     ;;
    d)       _MODE__SELECT_=$__MODE_DEBUG__     ;;
    DEBUG)   _MODE__SELECT_=$__MODE_DEBUG__     ;;
    debug)   _MODE__SELECT_=$__MODE_DEBUG__     ;;
    *)       _MODE__SELECT_=$__MODE_RELEASE     ;;
esac

FILE_NAME=$0

# ( yes "" | head -n $_MODE__SELECT_ | head -n-1  ; tail $FILE_NAME -n+$_MODE__SELECT_ ) | head -n 55

( yes "" | head -n $_MODE__SELECT_ | head -n-1  ; tail $FILE_NAME -n+$_MODE__SELECT_ ) | $__DOTNET_CSC -nologo -t:library \
  -r:'../../OxygenNotIncluded_Data/Managed/0Harmony.dll' \
  -r:'../../OxygenNotIncluded_Data/Managed/System.dll' \
  -r:'../../OxygenNotIncluded_Data/Managed/System.Core.dll' \
  -r:'../../OxygenNotIncluded_Data/Managed/UnityEngine.dll' \
  -r:'../../OxygenNotIncluded_Data/Managed/UnityEngine.CoreModule.dll' \
  -r:'../../OxygenNotIncluded_Data/Managed/mscorlib.dll' \
  -r:'../../OxygenNotIncluded_Data/Managed/Assembly-CSharp.dll' \
  -r:'../../OxygenNotIncluded_Data/Managed/Assembly-CSharp-firstpass.dll' \
  -out:'./'"${FILE_NAME%.*}".dll \
  -optimize \
  -

cp -f * ~/.config/unity3d/Klei/Oxygen\ Not\ Included/mods/Local/local
exit



#define VERBOSE
#define DEBUG



using KMod;
using HarmonyLib;
using UnityEngine;

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using Database;




namespace ONIMod
{
    public class MyUserMod : UserMod2 {
        public static float conduit_mul=100f;//导管容量以及一切使用导管的物品使用液体的速度乘数
        public static int SolidTransferArm_pickupRange=49;//机械臂的拾取范围
        public override void OnLoad(Harmony harmony)
        {
            Harmony.DEBUG = true;/*
            harmony.PatchAll(typeof(KilnConfigConfgiureRecipes));
            Debug.Log("Neutron3529:窑炉制造一切-加载完成");
            harmony.PatchAll(typeof(BatteryEnergySim200ms));
            Debug.Log("Neutron3529:电池发电-加载完成");
            harmony.PatchAll(typeof(MinionStartingStatsApplyAptitudes));
            Debug.Log("Neutron3529:每学习一个技能的士气加值-加载完成");
            harmony.PatchAll(typeof(WorkerWork));
            Debug.Log("Neutron3529:工作速度与经验加值-加载完成");
            harmony.PatchAll(typeof(AutoMinerConfigDoPostConfigureComplete));
            Debug.Log("Neutron3529:矿机采矿范围扩大-加载完成");
            harmony.PatchAll(typeof(AutoMinerUpdateDig));
            Debug.Log("Neutron3529:矿机采矿速度x100-加载完成");
            harmony.PatchAll(typeof(AutoMinerValidDigCell));
            Debug.Log("Neutron3529:矿机可采大部分矿物-加载完成");
            harmony.PatchAll(typeof(AutoMinerDigBlockingCB));
            Debug.Log("Neutron3529:矿机可以透过遮挡矿物进行采矿-加载完成");
            harmony.PatchAll(typeof(SolidTransferArmConstructor));
            harmony.PatchAll(typeof(SolidTransferArmConfigDoPostConfigureComplete));
            harmony.PatchAll(typeof(SolidTransferArmConfigAddVisualizer));
            Debug.Log("Neutron3529:机械臂拾取范围扩大-加载完成");
            harmony.PatchAll(typeof(Storage_ctor_ConfigureBuildingTemplate));
            Debug.Log("Neutron3529:存储箱容量扩大-加载完成");
            harmony.PatchAll(typeof(Research_ConfigureBuildingTemplate));
            Debug.Log("Neutron3529:研究站工作速度增加-加载完成");
            harmony.PatchAll(typeof(WireGetMaxWattageAsFloat));
            Debug.Log("Neutron3529:电线输电量扩大-加载完成");
            harmony.PatchAll(typeof(ConduitFlowConduitFlow));
            Debug.Log("Neutron3529:导管承载力扩大-加载完成");
            harmony.PatchAll(typeof(consumptionRateConfigureBuildingTemplate));
            Debug.Log("Neutron3529:几个液体工作速率调整-加载完成");
            harmony.PatchAll(typeof(BipedTransitionLayerBeginTransition));
            Debug.Log("Neutron3529:小人运动速度-加载完成");
            harmony.PatchAll(typeof(SolidTransferArmAsyncUpdate));
            Debug.Log("Neutron3529:机械臂拾取无视条件-加载完成");*/
            base.OnLoad(harmony);
            Debug.Log("Neutron3529's ONI mod is loaded.");
        }
        [HarmonyPatch(typeof(KilnConfig), "ConfgiureRecipes")]
        class KilnConfigConfgiureRecipes{ // 窑炉制造一切
            private static Tag tag3 = SimHashes.Sand.CreateTag();
            private static void addRecipe(Tag tag,float amount=10000f,int order=3){
                ComplexRecipe.RecipeElement[] array5 = new ComplexRecipe.RecipeElement[]
                {
                    new ComplexRecipe.RecipeElement(tag3, 1f)
                };
                ComplexRecipe.RecipeElement[] array6 = new ComplexRecipe.RecipeElement[]
                {
                    new ComplexRecipe.RecipeElement(tag, amount)
                };
                string obsolete_id3 = ComplexRecipeManager.MakeObsoleteRecipeID("Kiln", tag);
                string text3 = ComplexRecipeManager.MakeRecipeID("Kiln", array5, array6);
                ComplexRecipe complexRecipe = new ComplexRecipe(text3, array5, array6);
                complexRecipe.time = 1f;
                complexRecipe.description = string.Format(STRINGS.BUILDINGS.PREFABS.ROCKCRUSHER.RECIPE_DESCRIPTION, tag3.ProperName(), tag.ProperName());
                complexRecipe.nameDisplay = ComplexRecipe.RecipeNameDisplay.IngredientToResult;
                complexRecipe.fabricators = new List<Tag>
                {
                    TagManager.Create("Kiln")
                };
                complexRecipe.sortOrder = order;
                ComplexRecipeManager.Get().AddObsoleteIDMapping(obsolete_id3, text3);
            }
            public static void Postfix()
            {
                addRecipe("BasicFabric",100f,2);
                addRecipe("CookedMeat",100f,3);
                addRecipe("Burger",100f,4);
                addRecipe("BerryPie",100f,5);
                addRecipe("OrbitalResearchDatabank",100f,6);
                /* 配方顺序是按固定顺序排列的，没办法通过调整这里的顺序进行修改。
                addRecipe("Niobium".ToTag());
                addRecipe("Steel".ToTag());
                addRecipe("Lead".ToTag());
                addRecipe("Tungsten".ToTag());
                addRecipe("TempConductorSolid".ToTag());
                addRecipe("SuperInsulator".ToTag());
                addRecipe("Fertilizer".ToTag());
                addRecipe("Ceramic".ToTag());
                addRecipe("Glass".ToTag());
                addRecipe("Algae".ToTag());
                addRecipe("Water".ToTag());
                addRecipe("Sand".ToTag());*/
                foreach (Element element in ElementLoader.elements)
                {
                    SimHashes a = element.id;
                    if (a != SimHashes.Vacuum && a != SimHashes.Void && a != SimHashes.Unobtanium && a != SimHashes.Syngas && a != SimHashes.SolidSyngas && a != SimHashes.MoltenSyngas && a!= SimHashes.COMPOSITION/* && a!= SimHashes.Niobium && a != SimHashes.Steel && a != SimHashes.Lead && a != SimHashes.Tungsten && a != SimHashes.TempConductorSolid && a != SimHashes.SuperInsulator && a != SimHashes.Fertilizer && a != SimHashes.Ceramic && a != SimHashes.Glass && a != SimHashes.Algae && a != SimHashes.Water && a != SimHashes.Sand*/)
                    {
                        if (a==SimHashes.CrushedIce || a==SimHashes.DirtyIce || a==SimHashes.SolidSuperCoolant || a==SimHashes.SolidOxygen || a==SimHashes.SolidHydrogen || a==SimHashes.SolidPetroleum || a==SimHashes.BrineIce){addRecipe(a.CreateTag(),10000f,200);}/*制造液体用*/
                        else if(a!= SimHashes.Niobium && a != SimHashes.Steel && a != SimHashes.Lead && a != SimHashes.Tungsten && a != SimHashes.TempConductorSolid && a != SimHashes.SuperInsulator && a != SimHashes.Fertilizer && a != SimHashes.Ceramic && a != SimHashes.Glass && a != SimHashes.Glass && a != SimHashes.Algae && a != SimHashes.Water && a != SimHashes.Sand && a != SimHashes.Polypropylene && a!=SimHashes.Obsidian && a!=SimHashes.Diamond && a!=SimHashes.Sucrose){
                        addRecipe(a.CreateTag(),10000f,300);}else{addRecipe(a.CreateTag(),10000f,100);}
                    }
                }
            }
        }
        [HarmonyPatch(typeof(Battery), "EnergySim200ms")]
        class BatteryEnergySim200ms{ // 电池发电
            public static void Prefix(Battery __instance,float dt){
                __instance.AddEnergy(__instance.joulesLostPerSecond * dt * 10000f);
            }
        }
        [HarmonyPatch(typeof(MinionStartingStats), "ApplyAptitudes")]
        class  MinionStartingStatsApplyAptitudes{ // 每学习一个技能的士气加值
            public static bool Prefix(GameObject go)
            {
                MinionResume component = go.GetComponent<MinionResume>();
                foreach (SkillGroup skill in new List<SkillGroup>(Db.Get().SkillGroups.resources)) {
                        component.SetAptitude(skill.Id, 15f);
                }
                return false;
            }
        }
        [HarmonyPatch(typeof(Worker), "Work")]
        class  WorkerWork{ // 工作速度与经验加值
            public static bool Prefix(ref float dt)
            {
                dt*=100f;
                return true;
            }
        }
        [HarmonyPatch(typeof(AutoMinerConfig), "DoPostConfigureComplete")]
        class AutoMinerConfigDoPostConfigureComplete{
            public static void Postfix(GameObject go){//矿机采矿范围扩大
                go.AddOrGet<LogicOperationalController>();
                AutoMiner autoMiner = go.AddOrGet<AutoMiner>();
                autoMiner.x = -19;
                autoMiner.width = 2-autoMiner.x*2;
                autoMiner.height = 40;
            }
        }
        [HarmonyPatch(typeof(AutoMiner), "UpdateDig")]
        class AutoMinerUpdateDig{
            public static bool Prefix(ref float dt){//矿机采矿速度x100
                dt*=100f;
                return true;
            }
        }
        [HarmonyPatch(typeof(AutoMiner), "ValidDigCell")]
        class AutoMinerValidDigCell{
            public static bool Prefix(ref bool __result, int cell){//矿机可采大部分矿物
                __result=Grid.Solid[cell] && (!Grid.Foundation[cell]) && Grid.Element[cell].hardness < 250;
                return false;
            }
        }
        [HarmonyPatch(typeof(AutoMiner), "DigBlockingCB")]
        class AutoMinerDigBlockingCB{
            public static bool Prefix(ref bool __result){//矿机可以透过遮挡矿物进行采矿
                __result=false;
                return false;
            }
        }
        [HarmonyDebug]
        [HarmonyPatch(typeof(SolidTransferArm), MethodType.Constructor)]
        class SolidTransferArmConstructor{
            static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions){//机械臂拾取范围扩大
                //this.pickupRange = 50;
                //this.max_carry_weight = 100000f;
                Debug.Log("Neutron3529:开始注入SolidTransferArm的Constructor");
                foreach (var instruction in instructions)
                {
                    /*if(instruction.opcode==OpCodes.Stfld && ((FieldInfo)instruction.operand).Name == "pickupRange"){
                        Debug.Log("           :Find pickupRange");
                        yield return new CodeInstruction(OpCodes.Ldc_I4,50);// do not work since DoPostConfigureComplete change it.
                        yield return new CodeInstruction(OpCodes.Add);
                    }else */if(instruction.opcode==OpCodes.Stfld && ((FieldInfo)instruction.operand).Name == "max_carry_weight"){
                        Debug.Log("           :Find max_carry_weight");
                        yield return new CodeInstruction(OpCodes.Ldc_R4,100000f);
                        yield return new CodeInstruction(OpCodes.Mul);
                    }
                    yield return instruction;//yield Ldarg_2 since it shouldn't be skipped.
                }
                Debug.Log("           :注入结束");
            }
        }
        [HarmonyDebug]
        [HarmonyPatch(typeof(MinionConfig), "AddMinionTraits")]
        class MinionConfigAddMinionTraits{
            static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions){//机械臂拾取范围扩大
                Debug.Log("Neutron3529:开始注入MinionConfig的AddMinionTraits");
                int counter=0;
                uint flag=0xDEADBEFF;
                string name="";
                // 1:CarryAmount *100f
                // 2:RadiationResistance +10000f
                // 3:Stamina deltaAttribute *0.0625f
                // 4:Calories deltaAttribute *0.0625f ->3
                // 5:Calories maxAttribute *10f
                // 6:Toxicity deltaAttribute +10f ->4, Toxicity/ImmuneLevel.deltaAttribute
                // 7:Bladder deltaAttribute *0.0625f->3
                foreach (var instruction in instructions)
                {
                    if(flag==0xDEADBEFF){
                        yield return instruction;
                        if(instruction.opcode==OpCodes.Callvirt){
                            Debug.Log("       [II]:开始复制人压力的Transpiler修改.");
                            flag=0;
                            MethodInfo DbGet = typeof(Db).GetMethod("Get");
                            FieldInfo ModifierSet_Amounts = typeof(ModifierSet).GetField("Amounts");
                            FieldInfo Amounts_Stress = typeof(Database.Amounts).GetField("Stress");
                            FieldInfo Stress_deltaAttribute = typeof(Klei.AI.Amount).GetField("deltaAttribute");
                            FieldInfo Resource_Id = typeof(Resource).GetField("Id");
                            ConstructorInfo AttributeModifier = typeof(Klei.AI.AttributeModifier).GetConstructor(new Type[]{typeof(string),typeof(float),typeof(string),typeof(bool),typeof(bool),typeof(bool)});
                            MethodInfo Modifier_Add = typeof(Klei.AI.Modifier).GetMethod("Add");
                            yield return new CodeInstruction(OpCodes.Dup,null);                     // 145	01D6	ldloc.0
                            yield return new CodeInstruction(OpCodes.Call,DbGet);                   // 146	01D7	call	class Db Db::Get()
                            yield return new CodeInstruction(OpCodes.Ldfld,ModifierSet_Amounts);    // 147	01DC	ldfld	class Database.Amounts ModifierSet::Amounts
                            yield return new CodeInstruction(OpCodes.Ldfld,Amounts_Stress);         // 148	01E1	ldfld	class Klei.AI.Amount Database.Amounts::Stamina
                            yield return new CodeInstruction(OpCodes.Ldfld,Stress_deltaAttribute);  // 149	01E6	ldfld	class Klei.AI.Attribute Klei.AI.Amount::deltaAttribute
                            yield return new CodeInstruction(OpCodes.Ldfld,Resource_Id);            // 150	01EB	ldfld	string ['Assembly-CSharp-firstpass']Resource::Id
                            yield return new CodeInstruction(OpCodes.Ldc_R4,-1f);                   // 151	01F0	ldc.r4	-0.116666667
                            yield return new CodeInstruction(OpCodes.Ldarg_0,null);                 // 152	01F5	ldarg.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 153	01F6	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 154	01F7	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_1,null);                // 155	01F8	ldc.i4.1
                            yield return new CodeInstruction(OpCodes.Newobj,AttributeModifier);     // 156	01F9	newobj	instance void Klei.AI.AttributeModifier::.ctor(string, float32, string, bool, bool, bool)
                            yield return new CodeInstruction(OpCodes.Callvirt,Modifier_Add);        // 157	01FE	callvirt	instance void Klei.AI.Modifier::Add(class Klei.AI.AttributeModifier)
                            Debug.Log("       [II]:复制人压力的Transpiler修改完成.");
                            Debug.Log("       [II]:开始复制人呼吸的Transpiler修改.");
                            FieldInfo Amounts_Breath = typeof(Database.Amounts).GetField("Breath");
                            yield return new CodeInstruction(OpCodes.Dup,null);                     // 145	01D6	ldloc.0
                            yield return new CodeInstruction(OpCodes.Call,DbGet);                   // 146	01D7	call	class Db Db::Get()
                            yield return new CodeInstruction(OpCodes.Ldfld,ModifierSet_Amounts);    // 147	01DC	ldfld	class Database.Amounts ModifierSet::Amounts
                            yield return new CodeInstruction(OpCodes.Ldfld,Amounts_Breath);         // 148	01E1	ldfld	class Klei.AI.Amount Database.Amounts::Stamina
                            yield return new CodeInstruction(OpCodes.Ldfld,Stress_deltaAttribute);  // 149	01E6	ldfld	class Klei.AI.Attribute Klei.AI.Amount::deltaAttribute
                            yield return new CodeInstruction(OpCodes.Ldfld,Resource_Id);            // 150	01EB	ldfld	string ['Assembly-CSharp-firstpass']Resource::Id
                            yield return new CodeInstruction(OpCodes.Ldc_R4,1f);                    // 151	01F0	ldc.r4	-0.116666667
                            yield return new CodeInstruction(OpCodes.Ldarg_0,null);                 // 152	01F5	ldarg.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 153	01F6	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 154	01F7	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_1,null);                // 155	01F8	ldc.i4.1
                            yield return new CodeInstruction(OpCodes.Newobj,AttributeModifier);     // 156	01F9	newobj	instance void Klei.AI.AttributeModifier::.ctor(string, float32, string, bool, bool, bool)
                            yield return new CodeInstruction(OpCodes.Callvirt,Modifier_Add);        // 157	01FE	callvirt	instance void Klei.AI.Modifier::Add(class Klei.AI.AttributeModifier)
                            Debug.Log("       [II]:复制人呼吸的Transpiler修改完成.");/*
                            Debug.Log("       [II]:开始复制人免疫的Transpiler修改.");
                            FieldInfo ModifierSet_Attribute = typeof(ModifierSet).GetField("Attributes");
                            FieldInfo Attributes_Immunity = typeof(Database.Attributes).GetField("Immunity");
                            yield return new CodeInstruction(OpCodes.Dup,null);                     // 121	0186	ldloc.0
                            yield return new CodeInstruction(OpCodes.Call,DbGet);                   // 122	0187	call	class Db Db::Get()
                            yield return new CodeInstruction(OpCodes.Ldfld,ModifierSet_Attribute);  // 123	018C	ldfld	class Database.Attributes ModifierSet::Attributes
                            yield return new CodeInstruction(OpCodes.Ldfld,Attributes_Immunity);    // 124	0191	ldfld	class Klei.AI.Attribute Database.Attributes::Sneezyness
                            //yield return new CodeInstruction(OpCodes.Ldfld,Stress_deltaAttribute);// 149	01E6	ldfld	class Klei.AI.Attribute Klei.AI.Amount::deltaAttribute
                            yield return new CodeInstruction(OpCodes.Ldfld,Resource_Id);            // 125	0196	ldfld	string ['Assembly-CSharp-firstpass']Resource::Id
                            yield return new CodeInstruction(OpCodes.Ldc_R4,100f);                  // 126	01F0	ldc.r4	0
                            yield return new CodeInstruction(OpCodes.Ldarg_0,null);                 // 127	01F5	ldarg.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 128	01F6	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 129	01F7	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_1,null);                // 130	01F8	ldc.i4.1
                            yield return new CodeInstruction(OpCodes.Newobj,AttributeModifier);     // 131	01A4	newobj	instance void Klei.AI.AttributeModifier::.ctor(string, float32, string, bool, bool, bool)
                            yield return new CodeInstruction(OpCodes.Callvirt,Modifier_Add);        // 132	01A9	callvirt	instance void Klei.AI.Modifier::Add(class Klei.AI.AttributeModifier)
                            Debug.Log("       [II]:复制人免疫的Transpiler修改完成.");
                            Debug.Log("       [II]:开始复制人抗病性的Transpiler修改.");
                            FieldInfo Attributes_GermResistance = typeof(Database.Attributes).GetField("GermResistance");
                            yield return new CodeInstruction(OpCodes.Dup,null);                     // 121	0186	ldloc.0
                            yield return new CodeInstruction(OpCodes.Call,DbGet);                   // 122	0187	call	class Db Db::Get()
                            yield return new CodeInstruction(OpCodes.Ldfld,ModifierSet_Attribute);  // 123	018C	ldfld	class Database.Attributes ModifierSet::Attributes
                            yield return new CodeInstruction(OpCodes.Ldfld,Attributes_GermResistance);// 124	0191	ldfld	class Klei.AI.Attribute Database.Attributes::Sneezyness
                            yield return new CodeInstruction(OpCodes.Ldfld,Resource_Id);            // 125	0196	ldfld	string ['Assembly-CSharp-firstpass']Resource::Id
                            yield return new CodeInstruction(OpCodes.Ldc_R4,100f);                  // 126	01F0	ldc.r4	0
                            yield return new CodeInstruction(OpCodes.Ldarg_0,null);                 // 127	01F5	ldarg.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 128	01F6	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 129	01F7	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_1,null);                // 130	01F8	ldc.i4.1
                            yield return new CodeInstruction(OpCodes.Newobj,AttributeModifier);     // 131	01A4	newobj	instance void Klei.AI.AttributeModifier::.ctor(string, float32, string, bool, bool, bool)
                            yield return new CodeInstruction(OpCodes.Callvirt,Modifier_Add);        // 132	01A9	callvirt	instance void Klei.AI.Modifier::Add(class Klei.AI.AttributeModifier)
                            Debug.Log("       [II]:复制人抗病性的Transpiler修改完成.");
                            Debug.Log("       [II]:开始复制人隔热的Transpiler修改.");
                            FieldInfo Attributes_Insulation = typeof(Database.Attributes).GetField("Insulation");
                            yield return new CodeInstruction(OpCodes.Dup,null);                     // 121	0186	ldloc.0
                            yield return new CodeInstruction(OpCodes.Call,DbGet);                   // 122	0187	call	class Db Db::Get()
                            yield return new CodeInstruction(OpCodes.Ldfld,ModifierSet_Attribute);  // 123	018C	ldfld	class Database.Attributes ModifierSet::Attributes
                            yield return new CodeInstruction(OpCodes.Ldfld,Attributes_Insulation);  // 124	0191	ldfld	class Klei.AI.Attribute Database.Attributes::Sneezyness
                            yield return new CodeInstruction(OpCodes.Ldfld,Resource_Id);            // 125	0196	ldfld	string ['Assembly-CSharp-firstpass']Resource::Id
                            yield return new CodeInstruction(OpCodes.Ldc_R4,100f);                  // 126	01F0	ldc.r4	0
                            yield return new CodeInstruction(OpCodes.Ldarg_0,null);                 // 127	01F5	ldarg.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 128	01F6	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_0,null);                // 129	01F7	ldc.i4.0
                            yield return new CodeInstruction(OpCodes.Ldc_I4_1,null);                // 130	01F8	ldc.i4.1
                            yield return new CodeInstruction(OpCodes.Newobj,AttributeModifier);     // 131	01A4	newobj	instance void Klei.AI.AttributeModifier::.ctor(string, float32, string, bool, bool, bool)
                            yield return new CodeInstruction(OpCodes.Callvirt,Modifier_Add);        // 132	01A9	callvirt	instance void Klei.AI.Modifier::Add(class Klei.AI.AttributeModifier)
                            Debug.Log("       [II]:复制人隔热的Transpiler修改完成.");*/
                        }
                    } else if(counter>0){
                        counter-=1;
                        if(counter>0){
                            yield return instruction;
                            continue;
                        }else{
                            CodeInstruction ins=instruction;
                            if(instruction.opcode==OpCodes.Ldc_R4){
                                float res=0f;
                                switch(flag){
                                    case 1:res=(float)instruction.operand*100f;break;
                                    case 2:res=(float)instruction.operand+10000f;break;
                                    case 3:res=(float)instruction.operand*-1f;break;
                                    case 4:res=(float)instruction.operand+100f;break;
                                    case 5:res=(float)instruction.operand*10f;break;
                                    default:flag=0;break;
                                }
                                if(flag!=0)ins=new CodeInstruction(OpCodes.Ldc_R4,res);
                                Debug.Log("       [II]:"+name+" : "+ins.ToString()+".");
                            }else{
                                Debug.Log("       [EE]:注入出现错误，flag="+flag.ToString()+"，opcode="+instruction.opcode.ToString()+"！");
                            }
                            flag=0;
                            yield return ins;
                        }
                    } else {
                        yield return instruction;
                        if(instruction.opcode==OpCodes.Ldfld){
                            name=((FieldInfo)instruction.operand).Name;
                            if(name == "CarryAmount"){
                                flag=1;counter=2;
                            } else if(name == "RadiationResistance"){
                                flag=2;counter=2;
                            } else if(name == "deltaAttribute"/* || name =="AirConsumptionRate"*/){
                                flag=3;counter=2;
                            } else if(name == "Toxicity" || name == "ImmuneLevel"){
                                flag=4;counter=3;
                            } else if(name == "maxAttribute"){
                                flag=5;counter=2;
                            } else {continue;}
                            Debug.Log("           :Target found! name="+name+", fc="+flag.ToString()+","+counter.ToString());
                        }
                    }
                }
                Debug.Log("           :注入结束");
            }
        }
        [HarmonyPatch(typeof(SolidTransferArmConfig), "DoPostConfigureComplete")]
        class SolidTransferArmConfigDoPostConfigureComplete{
            public static void Postfix(GameObject go){//机械臂拾取范围扩大
                go.AddOrGet<SolidTransferArm>().pickupRange = SolidTransferArm_pickupRange;
            }
        }
        [HarmonyPatch(typeof(SolidTransferArmConfig), "AddVisualizer")]
        class SolidTransferArmConfigAddVisualizer{
            public static bool Prefix(GameObject prefab, bool movable){//机械臂拾取范围扩大--可视化
                StationaryChoreRangeVisualizer stationaryChoreRangeVisualizer = prefab.AddOrGet<StationaryChoreRangeVisualizer>();
                stationaryChoreRangeVisualizer.x = -SolidTransferArm_pickupRange;
                stationaryChoreRangeVisualizer.y = -SolidTransferArm_pickupRange;
                stationaryChoreRangeVisualizer.width = SolidTransferArm_pickupRange*2+1;
                stationaryChoreRangeVisualizer.height = SolidTransferArm_pickupRange*2+1;
                stationaryChoreRangeVisualizer.movable = movable;
                return false;
            }
        }

        [HarmonyDebug]
        [HarmonyPatch]
        public static class RocketSolidLiquidGas_DoPostConfigureComplete {// used for 2  FactorySystem functions.
            static IEnumerable<MethodBase> TargetMethods()
            {
                yield return AccessTools.Method(typeof(RocketInteriorSolidOutputConfig), "DoPostConfigureComplete");
                yield return AccessTools.Method(typeof(RocketInteriorLiquidOutputConfig), "DoPostConfigureComplete");
                yield return AccessTools.Method(typeof(RocketInteriorGasOutputConfig), "DoPostConfigureComplete");
                yield return AccessTools.Method(typeof(RocketInteriorSolidInputConfig), "DoPostConfigureComplete");
                yield return AccessTools.Method(typeof(RocketInteriorLiquidInputConfig), "DoPostConfigureComplete");
                yield return AccessTools.Method(typeof(RocketInteriorGasInputConfig), "DoPostConfigureComplete");
            }
            static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) {
                Debug.Log("Neutron3529:开始注入RocketSolidLiquidGas_DoPostConfigureComplete方法");
                foreach (var instruction in instructions)
                {
                    if(instruction.opcode==OpCodes.Stfld && (((FieldInfo)instruction.operand).Name == "capacityKg")){
                        Debug.Log("           :Find "+((FieldInfo)instruction.operand).Name+", mul by `conduit_mul`");
                        yield return new CodeInstruction(OpCodes.Ldc_R4,conduit_mul);
                        yield return new CodeInstruction(OpCodes.Mul);
                    }
                    yield return instruction;//yield Ldarg_2 since it shouldn't be skipped.
                }
                Debug.Log("           :注入结束");
            }
        }


        [HarmonyDebug]
        [HarmonyPatch]
        public static class Storage_ctor_ConfigureBuildingTemplate {// used for 2  FactorySystem functions.
            static IEnumerable<MethodBase> TargetMethods()
            {
                /*Type[] t=typeof(Building).Assembly.GetTypes();
                foreach(Type ty in t){
                    MethodInfo[] m=ty.GetMethods();
                    foreach(MethodInfo i in m)if(i.Name=="ConfigureBuildingTemplate"){
                        Debug.Log("Neutron3529:准备注入类别"+ty.ToString()+"的ConfigureBuildingTemplate方法");
                        yield return i;
                    }
                }*/

                yield return AccessTools.Method(typeof(GasReservoirConfig), "ConfigureBuildingTemplate");
                yield return AccessTools.Method(typeof(LiquidReservoirConfig), "ConfigureBuildingTemplate");
                yield return AccessTools.Method(typeof(RefrigeratorConfig), "DoPostConfigureComplete");
                yield return typeof(Storage).GetConstructor(new Type[]{});
            }
            static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) {
                Debug.Log("Neutron3529:开始注入Storage-ConfigureBuildingTemplate方法");
                foreach (var instruction in instructions)
                {
                    if(instruction.opcode==OpCodes.Stfld && (((FieldInfo)instruction.operand).Name == "capacityKg"||((FieldInfo)instruction.operand).Name == "capacity")){
                        Debug.Log("           :Find "+((FieldInfo)instruction.operand).Name+", mul by 10000f");
                        yield return new CodeInstruction(OpCodes.Ldc_R4,10000f);
                        yield return new CodeInstruction(OpCodes.Mul);
                    }
                    yield return instruction;//yield Ldarg_2 since it shouldn't be skipped.
                }
                Debug.Log("           :注入结束");
            }
        }

        [HarmonyDebug]
        [HarmonyPatch]
        public static class Research_ConfigureBuildingTemplate {// used for 2  FactorySystem functions.
            static IEnumerable<MethodBase> TargetMethods()
            {
                Type[] t=typeof(Building).Assembly.GetTypes();
                foreach(Type ty in t){
                    if(ty.ToString().IndexOf("Center")>=0 || ty.ToString().IndexOf("Research")>=0){
                        MethodInfo[] m=ty.GetMethods();
                        foreach(MethodInfo i in m)if(i.Name=="ConfigureBuildingTemplate"){
                            Debug.Log("Neutron3529:准备注入类别"+ty.ToString()+"的ConfigureBuildingTemplate方法");
                            yield return i;
                        }
                    }
                }
            }
            static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) {
                Debug.Log("Neutron3529:开始注入(Research?)ConfigureBuildingTemplate方法");
                foreach (var instruction in instructions)
                {
                    if(instruction.opcode==OpCodes.Stfld && ((FieldInfo)instruction.operand).Name == "capacity"){
                        Debug.Log("           :Find "+((FieldInfo)instruction.operand).Name+", mul by 100f");
                        yield return new CodeInstruction(OpCodes.Ldc_R4,100f);
                        yield return new CodeInstruction(OpCodes.Mul);
                    }else if(instruction.opcode==OpCodes.Stfld && (((FieldInfo)instruction.operand).Name == "mass_per_point"||((FieldInfo)instruction.operand).Name == "materialPerPoint"||((FieldInfo)instruction.operand).Name == "timePerPoint")){
                        Debug.Log("           :Find "+((FieldInfo)instruction.operand).Name+", mul by 0.015625f");
                        yield return new CodeInstruction(OpCodes.Ldc_R4,0.015625f);
                        yield return new CodeInstruction(OpCodes.Mul);
                    }
                    yield return instruction;//yield Ldarg_2 since it shouldn't be skipped.
                }
                Debug.Log("           :注入结束");
            }
        }
        [HarmonyPatch(typeof(Wire), "GetMaxWattageAsFloat")]
        class WireGetMaxWattageAsFloat{
            public static void Postfix(ref float __result){//电线输电量扩大
                __result*=1000f;
            }
        }
        [HarmonyPatch(typeof(ConduitFlow),MethodType.Constructor, new[]{typeof(ConduitType),typeof(int),typeof(IUtilityNetworkMgr),typeof(float),typeof(float)})]
        class ConduitFlowConduitFlow{
            public static void Prefix(ref float max_conduit_mass){//导管承载力扩大
                max_conduit_mass*=conduit_mul;
            }
        }
        [HarmonyPatch(typeof(SolidConduitInboxConfig), "DoPostConfigureComplete")]
        class SolidConduitInboxConfigDoPostConfigureComplete{
            public static void Postfix(GameObject go){
                go.AddOrGet<Storage>().capacityKg*=conduit_mul;
            }
        }
        [HarmonyPatch(typeof(SolidConduitDispenser), "ConduitUpdate")]
        class SolidConduitDispenserConduitUpdate{
            static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
            {
                int counter=0;
                Debug.Log("Neutron3529:Transpiler of SolidConduitDispenser.ConduitUpdate start.");
                foreach (var instruction in instructions)
                {
                    if(instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 20f){counter++;yield return new CodeInstruction(OpCodes.Ldc_R4,20f*conduit_mul);}else{yield return instruction;}
                }
                Debug.Log(string.Format("           :Transpiler counter is {0:N}",counter));
            }
        }
        [HarmonyPatch]
        class consumptionRateConfigureBuildingTemplate{
            static IEnumerable<MethodBase> TargetMethods()
            {
                yield return AccessTools.Method(typeof(AirConditionerConfig), "ConfigureBuildingTemplate");//空调
                yield return AccessTools.Method(typeof(LiquidConditionerConfig), "ConfigureBuildingTemplate");//液体空调
            }
            public static void Postfix(GameObject go){
                go.AddOrGet<ConduitConsumer>().consumptionRate *= conduit_mul;
                go.AddOrGet<Storage>().capacityKg *= conduit_mul;
            }
        }
        [HarmonyPatch]
        class consumptionRateDoPostConfigureComplete{
            static IEnumerable<MethodBase> TargetMethods()
            {
                yield return AccessTools.Method(typeof(GasPumpConfig), "DoPostConfigureComplete");//泵
                //yield return AccessTools.Method(typeof(GasMiniPumpConfig), "DoPostConfigureComplete");//泵
                yield return AccessTools.Method(typeof(LiquidPumpConfig), "DoPostConfigureComplete");//泵
                //yield return AccessTools.Method(typeof(LiquidMiniPumpConfig), "DoPostConfigureComplete");//泵
            }
            public static void Postfix(GameObject go){
                go.AddOrGet<ElementConsumer>().consumptionRate *= conduit_mul;
                go.AddOrGet<Storage>().capacityKg *= conduit_mul;
            }
        }
        [HarmonyPatch(typeof(BipedTransitionLayer), "BeginTransition")]
        class BipedTransitionLayerBeginTransition{//小人运动速度
            public static void Postfix(Navigator navigator, Navigator.ActiveTransition transition){
                transition.animSpeed*=Mathf.Max(35f/transition.speed,1);
                transition.speed=Mathf.Max(35f,transition.speed);
            }
        }
        [HarmonyPatch(typeof(SolidTransferArm), "AsyncUpdate")]
        class SolidTransferArmAsyncUpdate{
            public static bool Prefix(SolidTransferArm __instance, ref bool __result, ref HashSet<int> ___reachableCells,GameObject game_object, ref List<Pickupable> ___pickupables, List<SolidTransferArm.CachedPickupable> ___cached_pickupables){
                bool is_update=false;// flag of !this.reachableCells.SetEquals(workspace);
                if (___reachableCells.Count<Grid.CellCount) {
                    is_update=true;
                    ___reachableCells.Clear();
                    for(int i=0;i<Grid.CellCount;i++){
                        ___reachableCells.Add(i);
                    }
                }
                ___pickupables.Clear();
                foreach (SolidTransferArm.CachedPickupable cachedPickupable in ___cached_pickupables)
                {
                    if (cachedPickupable.pickupable.KPrefabID.HasAnyTags(ref SolidTransferArm.tagBits) //__instance.IsPickupableRelevantToMyInterests(cachedPickupable.pickupable.KPrefabID, cachedPickupable.storage_cell)
                        && cachedPickupable.pickupable.CouldBePickedUpByTransferArm(game_object)) {
                        ___pickupables.Add(cachedPickupable.pickupable);
                    }
                }
                __result=is_update;
                return false;
            } // Prefix version have a infinite range and could be faster.
//             static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
//             {
//                 MethodInfo IsPhysicallyAccessible = typeof(Grid).GetMethod("IsPhysicallyAccessible");
//                 /*int num3 = Grid.XYToCell(j, i);
//                 bool flag = Grid.IsValidCell(num3) && Grid.IsPhysicallyAccessible(num, num2, j, i, true);
//                 if (flag)
//                 {
//                     workspace.Add(num3);
//                 }
//
//                 ->
//                 if (Grid.IsValidCell(num3))
//                     workspace.Add(Grid.XYToCell(j, i))
//                 */
//                 var codes = new List<CodeInstruction>(instructions);
//                 int counter=0;
//                 Debug.Log("Neutron3529:Transpiler of SolidTransferArm.AsyncUpdate start.");
//                 foreach (var instruction in instructions)
//                 {
//                     if(counter!=1){
//                         yield return instruction;//yield Ldarg_2 since it shouldn't be skipped.
//                     } else {
//                         yield return new CodeInstruction(OpCodes.Pop,null);
//                         counter+=1;
//                     }
//                     if(counter==0){
//                         if(instruction.opcode == OpCodes.Call && instruction.operand as MethodInfo == IsPhysicallyAccessible){counter+=1;}
//                     }
//                 }
//                 Debug.Log(string.Format("           :Transpiler counter is {0:N}",counter));
//             }
        }
//         [HarmonyPatch(typeof(SolidTransferArm), "AsyncUpdate")]
//         class SolidTransferArmAsyncUpdate{
//             static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
//             {
//                 MethodInfo XY = typeof(Grid).GetMethod("XYToCell",new Type[] {typeof(int),typeof(int)});
//                 /*int num3 = Grid.XYToCell(j, i);
//                 bool flag = Grid.IsValidCell(num3) && Grid.IsPhysicallyAccessible(num, num2, j, i, true);
//                 if (flag)
//                 {
//                     workspace.Add(num3);
//                 }
//
//                 ->
//                     workspace.Add(Grid.XYToCell(j, i))
//                 */
//                 var codes = new List<CodeInstruction>(instructions);
//                 int counter=-1;
//                 int ins=0;
//                 Debug.Log("Neutron3529:Transpiler of SolidTransferArm.AsyncUpdate start.");
//                 foreach (var instruction in instructions)
//                 {
//                     if(counter!=1){
//                         Debug.Log(ins.ToString("D")+" "+instruction.ToString());
//                         yield return instruction;//yield Grid.XYToCell(j, i)
//                         if(counter==0){counter+=1;}//yield the native stloc
//                     }else{
//                         if(instruction.opcode == OpCodes.Ldarg_2){//arg2=workspace.
//                             counter+=1;
//                             yield return instruction;//yield Ldarg_2 since it shouldn't be skipped.
//                         }
//                     }
//                     if (instruction.opcode == OpCodes.Call && instruction.operand as MethodInfo == XY){
//                         counter+=1;//calculate how much Grid.XYToCell is called..
//                     }
//                     ins++;
//                 }
//                 Debug.Log(string.Format("           :Transpiler counter is {0:N}",counter));
//             }
//         }
    }
}

